<?php

class Helper_ImCode
{
	/**
     * 生成的验证码
     *
     * @var string
     */
    public $_code;

    /**
     * 验证码过期时间
     *
     * @var string
     */
    public $_expired;

    /**
     * 验证码图片的类型（默认为 jpeg）
     *
     * @var string
     */
    public $imagetype = 'jpeg';

    /**
     * 指示是否在生成验证码图片时保留已有的验证码
     *
     * 保留已有的验证码可以让用户在各个不同的页面都看到一致的验证码。
     * 只有这个验证码使用后，已有的验证码才会失效。
     *
     * @var boolean
     */
    public $keepCode = false;

	public function __construct(){
			@session_start();

			$this->_code = isset($_SESSION['IMGCODE']) ?
					$_SESSION['IMGCODE'] : '';
			$this->_expired = isset($_SESSION['IMGCODE_EXPIRED']) ?
					$_SESSION['IMGCODE_EXPIRED'] : 0;
	}


	public function check($code)
    {
        $time = time();
        if ($time >= $this->_expired || strtoupper($code) != strtoupper($this->_code)) {
            return false;
        }
        return true;
    }

	public function checkCaseSensitive($code)
    {
        $time = time();
        if ($time >= $this->_expired || $code != $this->_code) {
            return false;
        }
        return true;
    }

    /**
     * 清除 session 中的 imgcode 相关信息
     */
    public function clear()
    {
        unset($_SESSION['IMGCODE']);
        unset($_SESSION['IMGCODE_EXPIRED']);
    }

    /**
     * 利用 GD 库产生验证码图像
     *
     * 目前 $options 参数支持下列选项：
     * -  paddingLeft, paddingRight, paddingTop, paddingBottom
     * -  border, borderColor
     * -  font, color, bgcolor
     *
     * 如果 font 为 0-5，则使用 GD 库内置的字体。
     * 如果要指定字体文件，则 font 选项必须为字体文件的绝对路径，例如：
     * <code>
     * $options = array('font' => '/var/www/example/myfont.gdf');
     * image($type, $length, $lefttime, $options);
     * </code>
     *
     * @param int $type 验证码包含的字符类型，0 - 数字、1 - 字母、其他值 - 数字和字母
     * @param int $length 验证码长度
     * @param int $leftime 验证码有效时间（秒）
     * @param array $options 附加选项，可以指定字体、宽度和高度等参数
     */
   public function image($type = 3, $length = 4, $lefttime = 900, $options = null){
		
		if ($this->keepCode && $this->_code != ''){
			$code = $this->_code;
		} else {
			// 生成验证码
			switch ($type){
				case 0:
					$seed = '3456789';
					break;
				case 1:
					$seed = 'ABCDEFGHJKLMNPQRTUVWXY';
					break;
				case 2:
					$seed = 'ABCDEFGHJKLMNPQRTUVWXYabcdefghjklmnpqrtuvwxy';
					break;
				default:
					$seed = '3456789ABCDEFGHJKLMNPQRTUVWXYabcdefghjklmnpqrtuvwxy';
			}
			// 默认为4位
			if ($length <= 0){ $length = 4; }
			$code = '';
			list($usec, $sec) = explode(" ", microtime());
            srand($sec + $usec * 100000);
            $len = strlen($seed) - 1;
			for ($i = 0; $i < $length; $i++){
				$code .= substr($seed, rand(0, $len), 1);
			}
			$_SESSION['IMGCODE'] = $code;
		}
		// 超时时间
		$_SESSION['IMGCODE_EXPIRED'] = time() + $lefttime;	

		// 图片大小
		$size_x = isset($options['size_x']) ? $options['size_x'] : 90;
		$size_y = isset($options['size_y']) ? $options['size_y'] : 30;

		// 计算字符的空间
		$space_per_char = $size_x / strlen($code);
		
		// 确定要使用的字体
		if (!isset($options['font'])){
            $font = dirname(__FILE__).'/arial.ttf';
        } else {
            $font = $options['font'];
        }

		// 随机线条数量
		if (!isset($options['lineNum'])){
			$lineNum = 100;
		} else {
			$lineNum = $options['lineNum'];
		}

		 // 创建画布
		$img = imagecreatetruecolor($size_x, $size_y);

		// 设置选项

		// 设置背景颜色
		if (!isset($options['background'])){
			$background = imagecolorallocate($img, 255, 255, 255);
		} else {
			list($r, $g, $b) = $this->_hex2rgb($options['background']);
			$background = imagecolorallocate($img, $r, $g, $b);
		}
		// 线条颜色
		if (!isset($options['border'])){
			$border = imagecolorallocate($img, 128, 128, 128);
		} else {
			list($r, $g, $b) = $this->_hex2rgb($options['border']);
			$border = imagecolorallocate($img, $r, $g, $b);
		}
		// 字体颜色
		if (!isset($options['colors'])){
			$colors[] = imagecolorallocate($img, 128, 64, 192);
			$colors[] = imagecolorallocate($img, 192, 64, 128);
			$colors[] = imagecolorallocate($img, 108, 192, 64);
		} else {
			foreach ($options['colors'] as $color){
				list($r, $g, $b) = $this->_hex2rgb($color);
				$colors[] = imagecolorallocate($img, $r, $g, $b);
			}
		}
       
        // 绘制背景
        imagefilledrectangle($img, 1, 1, $size_x - 2, $size_y - 2, $background);
		// 绘制边框
		imagerectangle($img, 0, 0, $size_x - 1, $size_y - 1, $border);

        // 绘制文字
		for ($i = 0; $i < strlen($code); $i++){
			$color = $colors[$i % count($colors)];
			imagettftext($img, 10 + rand(6, 8), -20 + rand(0, 30), ($i + 0.3) * $space_per_char, 15 + rand(0, 10), $color, $font, $code{$i});
		}

		// 增加随机变形处理
		imageantialias($img, true);

		// 增加随机线条
		for ($i = 0; $i < $lineNum; $i++){
			$x1 = rand(5, $size_x - 5);
			$y1 = rand(5, $size_y - 5);
			$x2 = $x1 - 4 + rand(0, 8);
			$y2 = $y1 - 4 + rand(0, 8);
			imageline($img, $x1, $y1, $x2, $y2, $colors[rand(0, count($colors) - 1)]);
		}

        // 输出图像
        switch (strtolower($this->imagetype)){
	        case 'png':
	            header("Content-type: " . image_type_to_mime_type(IMAGETYPE_PNG));
	            imagepng($img);
	            break;
	        case 'gif':
	            header("Content-type: " . image_type_to_mime_type(IMAGETYPE_GIF));
	            imagegif($img);
	            break;
	        case 'jpg':
	        default:
	            header("Content-type: " . image_type_to_mime_type(IMAGETYPE_JPEG));
	            imagejpeg($img);
        }
        imagedestroy($img);
        unset($img);		
	}

    /**
     * 将 16 进制颜色值转换为 rgb 值
     *
     * @param string $hex
     *
     * @return array
     */
   public function _hex2rgb($color, $defualt = 'ffffff')
    {
        $color = strtolower($color);
        if (substr($color, 0, 2) == '0x') {
            $color = substr($color, 2);
        } elseif (substr($color, 0, 1) == '#') {
            $color = substr($color, 1);
        }
        $l = strlen($color);
        if ($l == 3) {
            $r = hexdec(substr($color, 0, 1));
            $g = hexdec(substr($color, 1, 1));
            $b = hexdec(substr($color, 2, 1));
            return array($r, $g, $b);
        } elseif ($l != 6) {
            $color = $defualt;
        }

        $r = hexdec(substr($color, 0, 2));
        $g = hexdec(substr($color, 2, 2));
        $b = hexdec(substr($color, 4, 2));
        return array($r, $g, $b);
    }
}
?>